import unittest
from scheme import *


class TestStringMethods(unittest.TestCase):

    def test_001(self):
        program = "2015"
        get = eval(parse(program))
        want = 2015
        self.assertEqual(get, want)

    def test_002(self):
        programs = [("(+ 2015 10)", 2025), ("(- 2015 10)", 2005)]
        for program, want in programs:
            get = eval(parse(program))
            self.assertEqual(get, want)

    def test_003(self):
        programs = [("(* 2015 10)", 20150), ("(/ 2015 10)", 201.5)]
        for program, want in programs:
            get = eval(parse(program))
            self.assertEqual(get, want)

    def test_004(self):
        programs = [
            ("(+ (* 3 5) (- 10 6))", 19),
        ]
        for program, want in programs:
            get = eval(parse(program))
            self.assertEqual(get, want)

    def test_005(self):
        programs = [
            ("(+ (* 3 5) (- 10 6))", 19),
        ]
        for program, want in programs:
            get = eval(parse(program))
            self.assertEqual(get, want)

    def test_006(self):
        program = "(define size 10)"
        eval(parse(program))
        self.assertEqual(global_env["size"], 10)

    def test_007(self):
        program = "(define size 10)"
        eval(parse(program))
        program = "(* size 10)"
        get = eval(parse(program))
        self.assertEqual(get, 100)

    def test_008(self):
        program = "(define radius 10)"
        eval(parse(program))
        program = "radius"
        get = eval(parse(program))
        self.assertEqual(get, 10)

    def test_009(self):
        program = "(define radius 10)"
        eval(parse(program))
        program = "(define circumference (* 2 pi radius))"
        eval(parse(program))
        program = "circumference"
        get = eval(parse(program))
        self.assertEqual(get, 62.83185307179586)

    def test_010(self):
        program = "(define (square x) (* x x))"
        eval(parse(program))
        program = "(square 10)"
        get = eval(parse(program))
        self.assertEqual(get, 100)
        program = "(square (+ 5 5))"
        get = eval(parse(program))
        self.assertEqual(get, 100)

    def test_011(self):
        program = "(define (add x y) (+ x y))"
        eval(parse(program))
        program = "(add 1 2)"
        get = eval(parse(program))
        self.assertEqual(get, 3)

    def test_012(self):
        program = "(define (square x) (* x x))"
        eval(parse(program))
        program = "(define (sum-of-squares x y)(+ (square x) (square y)))"
        eval(parse(program))

        program = "(sum-of-squares 3 4)"
        get = eval(parse(program))
        self.assertEqual(get, 25)

    def test_013(self):
        program = """
            (define (factorial n)
            (if (= n 1)
            1
            (* n (factorial (- n 1)))))
        """
        eval(parse(program))
        program = "(factorial 5)"
        get = eval(parse(program))
        self.assertEqual(get, 120)


if __name__ == "__main__":
    unittest.main()
